﻿using Interface.DAO;
using JMI_Nucleo.Classe;
using JMI_Nucleo.Enumerador;
using JMI_Nucleo.JMIProvider;
using OR;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dao
{
    public class FuncionarioDao : IFuncionarioDao<mFuncionario>
    {
        private mFuncionario infoFuncionario;
        private IEnderecoDao<mEndereco> daoEndereco;
        private IPessoaDao<mPessoa> daoPessoa;
        private IContatoDao<mContato> daoContato;

        public FuncionarioDao()
        {
            daoEndereco = DaoFactory<EnderecoDao>.Create();
            daoPessoa = DaoFactory<PessoaDao>.Create();
            daoContato = DaoFactory<ContatoDao>.Create();
        }

        #region Comando SQL
        const string cmdInsertSQL = @"INSERT INTO cadastro.funcionario(datacadastro, empresa, usuario, dataalteracao, 
                                      ativo, codigo, pessoa, endereco, contato, comissaovista, comissaoprazo, 
                                      comissaopromocao, funcao, admissao, demissao, obs, categoria, porcentpedido, 
                                      transferidopda, situacaoregistropda) 
                                      VALUES(@datacadastro, @empresa, @usuario, @dataalteracao, 
                                      @ativo, @codigo, @pessoa, @endereco, @contato, @comissaovista, @comissaoprazo, 
                                      @comissaopromocao, @funcao, @admissao, @demissao, @obs, @categoria, @porcentpedido, 
                                      @transferidopda, @situacaoregistropda)";

        const string cmdUpdateSQL = @"UPDATE cadastro.funcionario
                                       SET dataalteracao=@dataalteracao, ativo=@ativo, pessoa=@pessoa, endereco=@endereco, 
                                           contato=@contato, comissaovista=@comissaovista, comissaoprazo=@comissaoprazo, 
                                           comissaopromocao=@comissaopromocao, funcao=@funcao, admissao=@admissao, 
                                           demissao=@demissao, obs=@obs, categoria=@categoria, porcentpedido=@porcentpedido, 
                                           transferidopda=@transferidopda, situacaoregistropda=@situacaoregistropda ";

        const string cmdDeleteSQL = @"DELETE FROM cadastro.funcionario ";

        const string cmdSelectSQL = @"SELECT F.datacadastro, F.dataalteracao, F.ativo, F.codigo, F.pessoa, F.contato, 
                                       F.comissaovista, F.comissaoprazo, F.comissaopromocao, F.empresa, F.endereco,
                                       F.funcao, F.admissao, F.demissao, F.obs, F.categoria, F.porcentpedido, F.transferidopda, 
                                       F.situacaoregistropda, P.nome, P.rg, P.cpf, C.telefone1, C.celular, C.email,
                                       E.tipologradouro, E.logradouro, E.numero, E.bairro, E.cidade, 
                                       E.cep, E.uf, E.complemento, E.tipo FROM cadastro.funcionario F
                                       LEFT OUTER JOIN cadastro.pessoa P
                                       ON (F.pessoa = P.indice AND F.empresa = P.empresa)
                                       LEFT OUTER JOIN cadastro.contato C 
                                       ON (F.pessoa = C.indice AND F.empresa = C.empresa)
                                       LEFT OUTER JOIN cadastro.endereco E
                                       ON (F.pessoa = E.indice AND F.empresa = E.empresa) ";

        const string cmdRetornaCodigo = @"SELECT F.codigo FROM cadastro.funcionario F, cadastro.pessoa P
                                WHERE (F.pessoa = P.indice AND F.codigo = P.empresa)
                                AND P.nome =@PAR_NOME";

        const string cmdRetornaApelido = @"SELECT P.nome FROM cadastro.funcionario F, cadastro.pessoa P
                                WHERE (F.pessoa = P.indice AND F.codigo = P.empresa)
                                AND F.codigo =@PAR_CODIGO";

        const string cmdRetornaListaNome = @"SELECT P.nome FROM cadastro.funcionario F
                                INNER JOIN cadastro.pessoa P 
                                ON (F.pessoa = P.indice AND F.codigo = P.empresa)
                                WHERE F.empresa =@PAR_EMPRESA ORDER BY P.nome";

        const string cmdConEmpresaPorFiltro = @"SELECT F.codigo, F.datacadastro, F.ativo, C.telefone1, P.nome FROM cadastro.funcionario F
                                LEFT OUTER JOIN cadastro.pessoa P ON (F.pessoa = P.indice AND F.empresa = P.empresa)
                                LEFT OUTER JOIN cadastro.contato C ON (F.contato = C.indice AND F.empresa = C.empresa) "; 
        #endregion

        #region Metodos publicos
        bool IFuncionarioDao<mFuncionario>.Inserir(mFuncionario infoFuncionario)
        {
            bool sucesso = false;
            try
            {
                infoFuncionario.Pessoa.Indice = UtilBD.GetID(EngineBD.GetConexao, "cadastro.pessoa", "indice", infoFuncionario.CodigoEmpresa);
                infoFuncionario.Pessoa.Empresa = infoFuncionario.CodigoEmpresa;
                sucesso = daoPessoa.Inserir(infoFuncionario.Pessoa);

                if (sucesso)
                {
                    infoFuncionario.Contato.Indice = UtilBD.GetID(EngineBD.GetConexao, "cadastro.contato", "indice", infoFuncionario.CodigoEmpresa);
                    infoFuncionario.Contato.Empresa = infoFuncionario.CodigoEmpresa;
                    sucesso = daoContato.Inserir(infoFuncionario.Contato);
                }
                if (sucesso)
                {
                    infoFuncionario.Endereco.Indice = UtilBD.GetID(EngineBD.GetConexao, "cadastro.endereco", "indice", infoFuncionario.CodigoEmpresa);
                    infoFuncionario.Endereco.Empresa = infoFuncionario.CodigoEmpresa;
                    sucesso = daoEndereco.Inserir(infoFuncionario.Endereco);
                }
                if (sucesso)
                {
                    DbCommand _cmd = EngineBD.GetConexao.CreateCommand();
                    _cmd.CommandType = CommandType.Text;
                    _cmd.CommandText = cmdInsertSQL;
                    GeraParametro(ref _cmd, infoFuncionario, 1);
                    _cmd.Prepare();
                    sucesso = EngineBD.ExecuteNonQuery(_cmd);
                }
            }
            catch (Exception ex)
            {
                #region Grava log local
                mLog _info = new mLog();
                _info._TipoErro = TipoErro.Erro;
                _info.Mensagem = "Erro ao executar comando. " + ex.Message;
                _info.Metodo = "bool IFuncionarioDao<mFuncionario>.Inserir(mFuncionario infoFuncionario)";
                _info.StackTrace = ex.StackTrace;
                _info.Tabela = String.Empty;
                LogLocal.Info = _info;
                LogLocal.Gravar();
                #endregion
            }
            return sucesso;
        }
        bool IFuncionarioDao<mFuncionario>.Alterar(mFuncionario infoFuncionario)
        {
            bool sucesso = false;
            DbParameter p = null;
            string cmdSQL = String.Empty;

            try
            {
                sucesso = daoPessoa.Alterar(infoFuncionario.Pessoa, infoFuncionario.Pessoa.Indice, infoFuncionario.Pessoa.Empresa);
                if (sucesso)
                    sucesso = daoContato.Alterar(infoFuncionario.Contato, infoFuncionario.Contato.Indice, infoFuncionario.Contato.Empresa);
                if (sucesso)
                    sucesso = daoEndereco.Alterar(infoFuncionario.Endereco, infoFuncionario.Endereco.Indice, infoFuncionario.CodigoEmpresa);

                DbCommand _cmd = EngineBD.GetConexao.CreateCommand();
                _cmd.CommandType = CommandType.Text;
                cmdSQL = cmdUpdateSQL;
                cmdSQL += "WHERE codigo =@PAR_CODIGO AND empresa =@PAR_EMPRESA";
                _cmd.CommandText = cmdSQL;

                GeraParametro(ref _cmd, infoFuncionario, 2);

                p = _cmd.CreateParameter();
                p.ParameterName = "@PAR_CODIGO";
                p.Value = infoFuncionario.Codigo;
                _cmd.Parameters.Add(p);

                p = _cmd.CreateParameter();
                p.ParameterName = "@PAR_EMPRESA";
                p.Value = infoFuncionario.CodigoEmpresa;
                _cmd.Parameters.Add(p);

                _cmd.Prepare();

                sucesso = EngineBD.ExecuteNonQuery(_cmd);
            }
            catch (Exception ex)
            {
                #region Grava log local
                mLog _info = new mLog();
                _info._TipoErro = TipoErro.Erro;
                _info.Mensagem = "Erro ao executar comando. " + ex.Message;
                _info.Metodo = "bool IFuncionarioDao<mFuncionario>.Alterar(mFuncionario infoFuncionario)";
                _info.StackTrace = ex.StackTrace;
                _info.Tabela = String.Empty;
                LogLocal.Info = _info;
                LogLocal.Gravar();
                #endregion
            }
            return sucesso;
        }
        bool IFuncionarioDao<mFuncionario>.Excluir(mFuncionario infoFuncionario)
        {
            bool sucesso = false;
            DbParameter p = null;
            string cmdSQL;

            try
            {
                // Excluir pessoa
                sucesso = daoPessoa.Excluir(infoFuncionario.Pessoa.Indice, infoFuncionario.CodigoEmpresa);
                // Excluir contato
                sucesso = daoContato.Excluir(infoFuncionario.Contato.Indice, infoFuncionario.CodigoEmpresa);
                // Excluir os possiveis endereços cadastrados
                daoEndereco.Excluir(infoFuncionario.Endereco.Indice, infoFuncionario.CodigoEmpresa);

                DbCommand _cmd = EngineBD.GetConexao.CreateCommand();

                _cmd.CommandType = CommandType.Text;
                cmdSQL = cmdDeleteSQL;
                cmdSQL += "WHERE codigo =@PAR_CODIGO AND empresa =@PAR_EMPRESA";
                _cmd.CommandText = cmdSQL;

                p = _cmd.CreateParameter();
                p.ParameterName = "@PAR_CODIGO";
                p.Value = infoFuncionario.Codigo;
                _cmd.Parameters.Add(p);

                p = _cmd.CreateParameter();
                p.ParameterName = "@PAR_EMPRESA";
                p.Value = infoFuncionario.CodigoEmpresa;
                _cmd.Parameters.Add(p);

                _cmd.Prepare();

                sucesso = EngineBD.ExecuteNonQuery(_cmd);
            }
            catch (Exception ex)
            {
                #region Grava log local
                mLog _info = new mLog();
                _info._TipoErro = TipoErro.Erro;
                _info.Mensagem = "Erro ao executar comando. " + ex.Message;
                _info.Metodo = "bool IFuncionarioDao<mFuncionario>.Excluir(mFuncionario infoFuncionario)";
                _info.StackTrace = ex.StackTrace;
                _info.Tabela = String.Empty;
                LogLocal.Info = _info;
                LogLocal.Gravar();
                #endregion
            }
            return sucesso;
        }

        mFuncionario IFuncionarioDao<mFuncionario>.GetFuncionario(int Codigo, short Empresa)
        {
            infoFuncionario = new mFuncionario();

            DbDataReader rd = null;
            DbCommand _cmd = null;
            DbParameter p = null;
            string cmdSQL = String.Empty;

            try
            {
                cmdSQL = cmdSelectSQL;
                cmdSQL += "WHERE F.codigo =@PAR_CODIGO AND F.empresa =@PAR_EMPRESA";

                _cmd = EngineBD.GetConexao.CreateCommand();
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdSQL;

                p = _cmd.CreateParameter();
                p.ParameterName = "@PAR_CODIGO";
                p.Value = Codigo;
                _cmd.Parameters.Add(p);

                p = _cmd.CreateParameter();
                p.ParameterName = "@PAR_EMPRESA";
                p.Value = Empresa;
                _cmd.Parameters.Add(p);

                rd = EngineBD.ExecuteDataReader(_cmd);

                if (rd.Read())
                    infoFuncionario = GetRd(rd);
            }
            finally
            {
                rd.Close();
            }
            return infoFuncionario;
        }
        
        List<string> IFuncionarioDao<mFuncionario>.GetListaNome(short Empresa)
        {
            List<string> lst = null;

            DbDataReader rd = null;
            DbCommand _cmd = null;

            try
            {
                _cmd = EngineBD.GetConexao.CreateCommand();

                DbParameter p = _cmd.CreateParameter();
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdRetornaListaNome;

                p.ParameterName = "@PAR_EMPRESA";
                p.Value = Empresa;
                _cmd.Parameters.Add(p);

                rd = EngineBD.ExecuteDataReader(_cmd);

                lst = new List<string>();
                while (rd.Read())
                {
                    lst.Add(rd["nome"].ToString());
                }
            }
            finally
            {
                rd.Close();
            }
            return lst;
        }
        List<mFuncionario> IFuncionarioDao<mFuncionario>.GetLista(short Empresa)
        {
            List<mFuncionario> lstFuncionario = new List<mFuncionario>();
            mFuncionario infoFuncionario = null;
            DbDataReader rd = null;
            DbCommand _cmd = null;
            string cmdSQL = String.Empty;

            try
            {
                cmdSQL = cmdSelectSQL;
                cmdSQL += "WHERE F.empresa =@PAR_EMPRESA ORDER BY P.nome";
                _cmd = EngineBD.GetConexao.CreateCommand();

                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdSQL;

                DbParameter p = _cmd.CreateParameter();
                p.ParameterName = "@PAR_EMPRESA";
                p.Value = Empresa;
                _cmd.Parameters.Add(p);

                rd = EngineBD.ExecuteDataReader(_cmd);

                while (rd.Read())
                {
                    infoFuncionario = GetRd(rd);
                    lstFuncionario.Add(infoFuncionario);
                }
            }
            finally
            {
                if (rd != null)
                    rd.Close();
            }
            return lstFuncionario;
        }

        short IFuncionarioDao<mFuncionario>.GetCodigo(string Nome)
        {
            short retorno = 0;

            DbDataReader rd = null;
            DbCommand _cmd = null;

            try
            {
                _cmd = EngineBD.GetConexao.CreateCommand();

                DbParameter p = _cmd.CreateParameter();
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdRetornaCodigo;

                p.ParameterName = "@PAR_NOME";
                p.Value = Nome;
                _cmd.Parameters.Add(p);

                rd = EngineBD.ExecuteDataReader(_cmd);

                if (rd.Read())
                    retorno = Convert.ToInt16(rd["codigo"]);
            }
            finally
            {
                rd.Close();
            }
            return retorno;
        }

        string IFuncionarioDao<mFuncionario>.GetNome(short Codigo)
        {
            string retorno = String.Empty;

            DbDataReader rd = null;
            DbCommand _cmd = null;

            try
            {
                _cmd = EngineBD.GetConexao.CreateCommand();

                DbParameter p = _cmd.CreateParameter();
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdRetornaCodigo;

                p.ParameterName = "@PAR_CODIGO";
                p.Value = Codigo;
                _cmd.Parameters.Add(p);

                rd = EngineBD.ExecuteDataReader(_cmd);

                if (rd.Read())
                    retorno = rd["nome"].ToString();
            }
            finally
            {
                rd.Close();
            }
            return retorno;
        }

        List<mFuncionario> IFuncionarioDao<mFuncionario>.GetListaPorFiltro(mFuncionario infoFuncionario)
        {
            List<mFuncionario> lstFuncionario = new List<mFuncionario>();
            DbDataReader rd = null;
            DbCommand _cmd = null;
            string cmdSQL = String.Empty;

            try
            {
                cmdSQL = cmdConEmpresaPorFiltro;

                _cmd = EngineBD.GetConexao.CreateCommand();

                _cmd.CommandType = CommandType.Text;
                _cmd.Parameters.Clear();

                if (!String.IsNullOrEmpty(infoFuncionario.Pessoa.Nome))
                {
                    cmdSQL += "WHERE P.nome = @PAR_NOME ";
                    UtilBD.AdicionaParametro(ref _cmd, "@PAR_NOME", infoFuncionario.Pessoa.Nome);
                }
           
                cmdSQL += "ORDER BY P.nome";
                _cmd.CommandText = cmdSQL;
                rd = EngineBD.ExecuteDataReader(_cmd);

                while (rd.Read())
                {
                    infoFuncionario.Codigo = Convert.ToInt16(rd["codigo"]);
                    infoFuncionario.DataCadastro = Convert.ToDateTime(rd["datacadastro"]);
                    infoFuncionario.Pessoa.Nome = rd["nome"].ToString();
                    infoFuncionario.Contato.Telefone1 = rd["telefone1"].ToString();
                    infoFuncionario.Ativo = Convert.ToBoolean(rd["ativo"]);
                    lstFuncionario.Add(infoFuncionario);
                    infoFuncionario = new mFuncionario();
                }
            }
            finally
            {
                if (rd != null)
                    rd.Close();
            }
            return lstFuncionario;
        }
        #endregion

        #region Metodos privados
        private mFuncionario GetRd(DbDataReader rd)
        {
            infoFuncionario = new mFuncionario();

            infoFuncionario.Codigo = Convert.ToInt32(rd["codigo"]);
            infoFuncionario.Pessoa = daoPessoa.GetPessoa(Convert.ToInt32(rd["pessoa"]), Convert.ToInt16(rd["empresa"]));
            infoFuncionario.Contato = daoContato.GetContato(Convert.ToInt32(rd["contato"]), Convert.ToInt16(rd["empresa"]));
            infoFuncionario.Endereco = daoEndereco.GetEndereco(Convert.ToInt32(rd["endereco"]), Convert.ToInt16(rd["empresa"]));
            infoFuncionario.CodigoCategoria = Convert.ToInt16(rd["categoria"]);
            infoFuncionario.DataCadastro = Convert.ToDateTime(rd["datacadastro"]);
            infoFuncionario.Ativo = Convert.ToBoolean(rd["ativo"]);
            infoFuncionario.DataAlteracao = Convert.ToDateTime(rd["dataalteracao"]);
            infoFuncionario.Funcao = rd["funcao"].ToString();
            infoFuncionario.Admissao = Convert.ToDateTime(rd["admissao"]);
            infoFuncionario.ComissaoVista = Convert.ToDecimal(rd["comissaovista"]);
            infoFuncionario.ComissaoPrazo = Convert.ToDecimal(rd["comissaoprazo"]);
            infoFuncionario.ComissaoPromocao = Convert.ToDecimal(rd["comissaopromocao"]);
            infoFuncionario.Observacao = rd["obs"].ToString();
    
            return infoFuncionario;
        }
        private void GeraParametro(ref DbCommand _cmd, mFuncionario infoFuncionario, byte Acao)
        {
            _cmd.Parameters.Clear();
     
            if (Acao == 1)
            {
                infoFuncionario.Codigo = UtilBD.GetID(EngineBD.GetConexao, "cadastro.funcionario", "codigo", infoFuncionario.CodigoEmpresa);
                UtilBD.AdicionaParametro(ref _cmd, "@codigo", infoFuncionario.Codigo);
                UtilBD.AdicionaParametro(ref _cmd, "@empresa", infoFuncionario.CodigoEmpresa);
                UtilBD.AdicionaParametro(ref _cmd, "@datacadastro", infoFuncionario.DataCadastro.ToShortDateString());
                UtilBD.AdicionaParametro(ref _cmd, "@usuario", infoFuncionario.CodigoUsuario);                
            }
            
            UtilBD.AdicionaParametro(ref _cmd, "@pessoa", infoFuncionario.Pessoa.Indice);
            UtilBD.AdicionaParametro(ref _cmd, "@ativo", infoFuncionario.Ativo);
            UtilBD.AdicionaParametro(ref _cmd, "@dataalteracao", infoFuncionario.DataAlteracao.ToShortDateString());
            UtilBD.AdicionaParametro(ref _cmd, "@categoria", infoFuncionario.CodigoCategoria);
            UtilBD.AdicionaParametro(ref _cmd, "@funcao", infoFuncionario.Funcao);
            UtilBD.AdicionaParametro(ref _cmd, "@admissao", infoFuncionario.Admissao.ToShortDateString());
            UtilBD.AdicionaParametro(ref _cmd, "@comissaovista", infoFuncionario.ComissaoVista);
            UtilBD.AdicionaParametro(ref _cmd, "@comissaoprazo", infoFuncionario.ComissaoPrazo);
            UtilBD.AdicionaParametro(ref _cmd, "@comissaopromocao", infoFuncionario.ComissaoPromocao);
            UtilBD.AdicionaParametro(ref _cmd, "@porcentpedido", infoFuncionario.PorcentPedido);
            UtilBD.AdicionaParametro(ref _cmd, "@obs", infoFuncionario.Observacao);
            UtilBD.AdicionaParametro(ref _cmd, "@demissao", infoFuncionario.Admissao.ToShortDateString());
            UtilBD.AdicionaParametro(ref _cmd, "@contato", infoFuncionario.Contato.Indice);
            UtilBD.AdicionaParametro(ref _cmd, "@endereco", infoFuncionario.Endereco.Indice);
            UtilBD.AdicionaParametro(ref _cmd, "@transferidopda", infoFuncionario.TransferidoPda);
            UtilBD.AdicionaParametro(ref _cmd, "@situacaoregistropda", infoFuncionario.SituacaoRegistroPda);
        }
        #endregion
    }
}
